package com.mdd.front.service.impl;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.mdd.common.core.AjaxResult;
import com.mdd.common.entity.AppOrder;
import com.mdd.common.entity.ExpressMessage;
import com.mdd.common.entity.FastArticleType;
import com.mdd.common.entity.FastType;
import com.mdd.common.entity.PayOrder;
import com.mdd.common.entity.log.LogMoney;
import com.mdd.common.entity.user.User;
import com.mdd.common.entity.user.UserAuth;
import com.mdd.common.enums.ClientEnum;
import com.mdd.common.enums.LogMoneyEnum;
import com.mdd.common.exception.OperateException;
import com.mdd.common.exception.PaymentException;
import com.mdd.common.mapper.AppOrderMapper;
import com.mdd.common.mapper.ExpressMessageMapper;
import com.mdd.common.mapper.FastArticleTypeMapper;
import com.mdd.common.mapper.FastTypeMapper;
import com.mdd.common.mapper.LogIntegralMapper;
import com.mdd.common.mapper.PayOrderMapper;
import com.mdd.common.mapper.delivery.ExpressCompanyMapper;
import com.mdd.common.mapper.log.LogMoneyMapper;
import com.mdd.common.mapper.user.UserAuthMapper;
import com.mdd.common.mapper.user.UserMapper;
import com.mdd.common.pay.alipay.AliPayConfigUtils;
import com.mdd.common.pay.alipay.AlipayHandle;
import com.mdd.common.pay.wxpay.WxConfig;
import com.mdd.common.pay.wxpay.WxPayConfigUtils;
import com.mdd.common.pay.wxpay.WxpayHandle;
import com.mdd.common.plugin.alipay.AliPayDriver;
import com.mdd.common.plugin.alipay.request.AliPaymentRequest;
import com.mdd.common.plugin.wechat.WxPayDriver;
import com.mdd.common.plugin.wechat.request.PaymentRequestV3;
import com.mdd.common.plugin.wechat.request.RefundRequestV3;
import com.mdd.common.util.AmountUtil;
import com.mdd.common.util.HttpUtils;
import com.mdd.common.util.RequestUtils;
import com.mdd.common.util.StringUtils;
import com.mdd.common.util.TimeUtils;
import com.mdd.common.util.ToolUtils;
import com.mdd.common.util.em.EMServiceUtil;
import com.mdd.front.service.IExpressDeliveryService;
import com.mdd.front.validate.PayVipValidate;
import com.mdd.front.vo.fast.CashbackGoldCoinDto;
import com.mdd.front.vo.fast.FastArticleTypeVo;
import com.mdd.front.vo.fast.FastTypeVo;
import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class ExpressDeliveryServiceImpl implements IExpressDeliveryService {

	@Autowired
	private FastTypeMapper fastTypeMapper;
	@Autowired
	private FastArticleTypeMapper fastArticleTypeMapper;
	@Autowired
	private PayOrderMapper payOrderMapper;
	@Autowired
	private AppOrderMapper appOrderMapper;
	@Autowired
	private AlipayHandle alipayHandle;
	@Autowired
	private WxpayHandle wxpayHandle;
	@Autowired
	private WxConfig wxConfig;
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private LogMoneyMapper logMoneyMapper;
	@Autowired
	private LogIntegralMapper logIntegralMapper;
	@Autowired
	private EMServiceUtil eMServiceUtil;
	@Autowired
	private ExpressMessageMapper expressMessageMapper;
	@Autowired
	private UserAuthMapper userAuthMapper;

	@Override
	public Map<String, Object> fastType() {
		List<FastType> fastTypeList = fastTypeMapper.selectList(new LambdaQueryWrapper<FastType>().orderByDesc(FastType::getSort));
		List<FastTypeVo> list = new LinkedList<FastTypeVo>();
		for (FastType fastType : fastTypeList) {
			FastTypeVo vo = new FastTypeVo();
			BeanUtils.copyProperties(fastType, vo);
			list.add(vo);
		}
//		List<FastTypeVo> list = new LinkedList<FastTypeVo>();
//		List<ExpressCompany> companyList = expressCompanyMapper.selectList(new LambdaQueryWrapper<ExpressCompany>().eq(ExpressCompany::getIsDelete, 0).orderByDesc(ExpressCompany::getSort));
//		companyList.stream().forEach( c ->{
//			FastTypeVo vo = new FastTypeVo();
//			vo.setId(c.getId());
//			vo.setName(c.getName());
//			vo.setIcon(c.getImage());
//			vo.setCode(c.getCodeKd());
//			vo.setRemark(c.getRemark());
//			vo.setPrice(c.getPrice() == null ? BigDecimal.ZERO : c.getPrice());
//			vo.setGoldCoin(c.getGoldCoin() == null ? BigDecimal.ZERO : c.getGoldCoin());
//			list.add(vo);
//		});
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("list", list);
		return map;
	}

	@Override
	public List<FastArticleTypeVo> fastActicleType() {
		List<FastArticleType> fastArticleTypeList = fastArticleTypeMapper.selectList(new LambdaQueryWrapper<FastArticleType>()
				.eq(FastArticleType::getParentId, 0).orderByDesc(FastArticleType::getSort));
		List<FastArticleTypeVo> list = new LinkedList<FastArticleTypeVo>();
		for (FastArticleType fastArticleType : fastArticleTypeList) {
			FastArticleTypeVo vo = new FastArticleTypeVo();
			BeanUtils.copyProperties(fastArticleType, vo);
			// 下级
			List<FastArticleType> selectList = fastArticleTypeMapper.selectList(new LambdaQueryWrapper<FastArticleType>().eq(FastArticleType::getParentId, fastArticleType.getId())
					.orderByDesc(FastArticleType::getSort));
			for (FastArticleType belowFastArticleType : selectList) {
				FastArticleTypeVo belowVo = new FastArticleTypeVo();
				BeanUtils.copyProperties(belowFastArticleType, belowVo);
				vo.getBelowList().add(belowVo);
			}
			list.add(vo);
		}
		return list;
	}
	private String getOpenidMnp(String code) {

		String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
				"wx03d3a4501c174a80", "b5ba2c574608a0fa9a3d3a2f31202a13", code);

		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpGet httpGet = new HttpGet(url);
		HttpResponse response;
		try {
			response = httpClient.execute(httpGet);
			String jsonResponse = EntityUtils.toString(response.getEntity());
			ObjectMapper objectMapper = new ObjectMapper();
			Map<String, String> result = objectMapper.readValue(jsonResponse, Map.class);
			String openid = result.get("openid");
//			String sessionKey = result.get("session_key");
			return openid;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";

	}

	@Override
	public AjaxResult<Object> payOrder(PayVipValidate requestObj, Integer userId,Integer terminal) {
		try {
			
			System.out.println("参数："+JSONObject.toJSONString(requestObj));
			
			// 校验快递订单号是否存在
			AppOrder appOrder = appOrderMapper.selectOne(new LambdaQueryWrapper<AppOrder>().eq(AppOrder::getOrdernum, requestObj.getKuaidiNum()));
			if(null == appOrder) {
				return AjaxResult.failed("订单号不存在");
			}
			String openId = null;
			UserAuth userAuth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
					.eq("user_id", userId)
//					.eq("terminal", terminal)
					.last("limit 1"));

			if (StringUtils.isNotNull(userAuth)) {
				openId = userAuth.getOpenid();
			}
			// 单独处理小程序
			if(terminal == ClientEnum.MNP.getCode()) {
				if(null == userAuth ) {
					userAuth = new UserAuth();
					userAuth.setUserId(userId);
					userAuth.setMnpOpenid(getOpenidMnp(requestObj.getCode()));
					userAuth.setCreateTime(System.currentTimeMillis() / 1000);
					userAuthMapper.insert(userAuth);
					openId = userAuth.getMnpOpenid();
				}else {
					if(StringUtils.isNotEmpty(userAuth.getMnpOpenid())) {
						openId = userAuth.getMnpOpenid();
					}else {
						openId = getOpenidMnp(requestObj.getCode());
						userAuth.setMnpOpenid(openId);
						userAuth.setUpdateTime(System.currentTimeMillis() / 1000);
						userAuthMapper.updateById(userAuth);
					}
				}
			}
			PayOrder order = new PayOrder();
			order.setUserId(userId);
			order.setRelatedId(requestObj.getBusinessId());
			order.setOrderSn(ToolUtils.get());
			order.setOrderType(1);
			order.setKuaidiNum(requestObj.getKuaidiNum());
			order.setPayStatus(0);
			order.setPayType(requestObj.getPayWay());
			order.setOrderAmount(appOrder.getPayprice());
			order.setCreateTime(TimeUtils.timestamp());
			order.setRemark("快递下单");
			payOrderMapper.insert(order);
			// 定义支付返回结果
			Map<String, String> map = new LinkedHashMap<>();
			switch (requestObj.getPayWay()) {
			case 1://余额
				User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userId).select(User::getId,User::getEarnings));
				if(null == user) {
					return AjaxResult.failed("用户不存在");
				}
				if(null == user.getEarnings() || user.getEarnings().compareTo(order.getOrderAmount()) < 0) {
					return AjaxResult.failed("余额不足");
				}
				BigDecimal subtract = user.getEarnings().subtract(order.getOrderAmount());
				user.setEarnings(subtract);
				userMapper.updateById(user);
				// 记录日志
				userBalanceChangeRecord(userId, order.getId(), order.getOrderSn(), order.getOrderAmount(), subtract, 2, "寄快递下单");
				order.setPayStatus(1);
				payOrderMapper.updateById(order);
				// 修改快递订单状态
				appOrder.setPaytype(String.valueOf(order.getPayType()));
				appOrder.setPayordernum("");
				appOrder.setPaystatus(1);
				appOrder.setPaytime(new Date());
				appOrderMapper.updateById(appOrder);
				// 通知
				String url = "https://kdapi.kdkdkd.cn:55800/kdapi/kdOrder/recOrderStatus";
				Map<String, String> param = new HashMap<String, String>();
				param.put("orderNum", order.getKuaidiNum());
				param.put("payStatus", "1");
				HttpUtils.doPostJson(url, JSONObject.toJSONString(param));
				return AjaxResult.success();
			case 2://微信
				if (terminal == ClientEnum.APK.getCode()) {
					return AjaxResult.success(wxpayHandle.createWxPayOrder(order.getOrderSn(), order.getOrderAmount().toPlainString(), order.getRemark(),WxPayConfigUtils.KUAIDINOTIFYURL));
				}
				PaymentRequestV3 requestV3 = new PaymentRequestV3();
				requestV3.setTerminal(terminal);
				requestV3.setOpenId(openId);
				requestV3.setAttach("kuaidian");
				requestV3.setOutTradeNo(order.getOrderSn());
				requestV3.setOrderAmount(order.getOrderAmount());
				requestV3.setDescription("快递下单");
				Object result = WxPayDriver.unifiedOrder(requestV3,WxPayConfigUtils.KUAIDMNPINOTIFYURL);
				if (terminal == ClientEnum.H5.getCode()) {
					Assert.notNull(requestObj.getRedirectUrl(), "redirectUrl参数缺失");
					String redirectUrl = RequestUtils.domain() + "/mobile" + requestObj.getRedirectUrl();
					String h5Url = result.toString() + "&redirect_url=" + URLEncoder.encode(redirectUrl, "UTF-8");
					map.put("url", h5Url);
					AjaxResult.success(map);
				}
				return AjaxResult.success(result);
			case 3://支付宝
				if (terminal == ClientEnum.APK.getCode()) {
					return AjaxResult.success(alipayHandle.createAliPayOrder(order.getOrderSn(), order.getOrderAmount().toPlainString(), order.getRemark(),AliPayConfigUtils.KUAIDINOTIFYURL));
				}
				AliPaymentRequest requestAiliPay = new AliPaymentRequest();
				requestAiliPay.setOutTradeNo(order.getOrderSn());
				requestAiliPay.setOrderAmount(order.getOrderAmount());
				requestAiliPay.setDescription("快递下单");
				requestAiliPay.setAttach("kuaidian");
				requestAiliPay.setUrl(requestObj.getRedirectUrl());
				Object resultAliPay = AliPayDriver.unifiedOrder(requestAiliPay);
				map.put("form", resultAliPay.toString());
				return AjaxResult.success(map);
			default:
				break;
			}
		} catch (OperateException e) {
			e.printStackTrace();
			throw new PaymentException(e.getMsg());
		} catch (Exception e) {
			e.printStackTrace();
			throw new PaymentException(e.getMessage());
		}

		return AjaxResult.failed("未知支付方式");
	}

	@Override
	public String notifyFromAlipay(Map<String, String> params) {
		//验证签名
		try {
			boolean flag = AlipaySignature.rsaCertCheckV1(params, AliPayConfigUtils.PUBLICCERTRAS2PATH, "UTF-8", "RSA2");
			if (flag) {
				String tradeStatus = params.get("trade_status");
				//签名验证通过,验证支付结果
				if ("TRADE_FINISHED".equals(tradeStatus)
						|| "TRADE_SUCCESS".equals(tradeStatus)) {
					String orderNo = params.get("out_trade_no");
					String tradeNo = params.get("trade_no");
					String totalAmount = params.get("total_amount");

					System.out.println("支付宝回调成功============================================tradeStatus："+tradeStatus);
					//以上两个状态代表支付成功
					PayOrder payOrder = payOrderMapper.selectOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderSn, orderNo));
					if(null == payOrder) {
						log.error("订单号不存在,支付失败 :" + orderNo);
						return "fail";
					}
					if(1 == payOrder.getPayStatus()) {
						log.error("订单已支付,忽略重复调用 :" + orderNo);
						return "success";
					}
					payOrder.setTradeNo(tradeNo);
					payOrder.setActualAmount(new BigDecimal(totalAmount));
					payOrder.setUpdateTime(TimeUtils.timestamp());
					payOrder.setPayStatus(1);
					payOrderMapper.updateById(payOrder);
					// 修改快递订单状态
					AppOrder appOrder = appOrderMapper.selectOne(new LambdaQueryWrapper<AppOrder>().eq(AppOrder::getOrdernum, payOrder.getKuaidiNum()));
					if(null != appOrder) {
						appOrder.setPaytype(String.valueOf(payOrder.getPayType()));
						appOrder.setPayordernum(tradeNo);
						appOrder.setPaystatus(1);
						appOrder.setPaytime(new Date());
						appOrderMapper.updateById(appOrder);
						// 通知
						String url = "https://kdapi.kdkdkd.cn:55800/kdapi/kdOrder/recOrderStatus";
						Map<String, String> param = new HashMap<String, String>();
						param.put("orderNum", payOrder.getKuaidiNum());
						param.put("payStatus", "1");
						HttpUtils.doPostJson(url, JSONObject.toJSONString(param));
					}
				}
			}
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		return "fail";
	}

	@Override
	@Transactional
	public String notifyFromWxpay(String notifyStr) {
		String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
		try {
			// 转换成map
			Map<String, String> resultMap = WXPayUtil.xmlToMap(notifyStr);
			WXPay wxPay = new WXPay(wxConfig);
			if (wxPay.isPayResultNotifySignatureValid(resultMap)) {
				String returnCode = resultMap.get("return_code");  //状态
				String orderNo = resultMap.get("out_trade_no");//商户订单号
				String tradeNo = resultMap.get("transaction_id"); //微信订单号
				String totalfee = resultMap.get("total_fee"); //微信订单号
				if (returnCode.equals("SUCCESS")) {
					//以上两个状态代表支付成功
					PayOrder payOrder = payOrderMapper.selectOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderSn, orderNo));
					if(null == payOrder) {
						log.error("订单号不存在,支付失败 :" + orderNo);
						return "fail";
					}
					if(1 == payOrder.getPayStatus()) {
						log.error("订单已支付,忽略重复调用 :" + orderNo);
						return "success";
					}
					payOrder.setTradeNo(tradeNo);
					payOrder.setActualAmount(new BigDecimal(String.valueOf(Double.valueOf(totalfee) / 100)));
					payOrder.setUpdateTime(TimeUtils.timestamp());
					payOrder.setPayStatus(1);
					payOrderMapper.updateById(payOrder);
					// 修改快递订单状态
					AppOrder appOrder = appOrderMapper.selectOne(new LambdaQueryWrapper<AppOrder>().eq(AppOrder::getOrdernum, payOrder.getKuaidiNum()));
					if(null != appOrder) {
						appOrder.setPaytype(String.valueOf(payOrder.getPayType()));
						appOrder.setPayordernum(tradeNo);
						appOrder.setPaystatus(1);
						appOrder.setPaytime(new Date());
						appOrderMapper.updateById(appOrder);
						// 通知
						String url = "https://kdapi.kdkdkd.cn:55800/kdapi/kdOrder/recOrderStatus";
						Map<String, String> param = new HashMap<String, String>();
						param.put("orderNum", payOrder.getKuaidiNum());
						param.put("payStatus", "1");
						HttpUtils.doPostJson(url, JSONObject.toJSONString(param));
					}
					xmlBack = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return xmlBack;
	}

	@Override
	public String notifyFromWxpayRefund(HttpServletRequest request) {
		try {
			//获得NotificationRequest对象
			NotificationRequest notificationRequest = wxpayHandle.getNotificationRequest(request);
			//获得微信支付通知报文解密结果
			Notification notification = wxpayHandle.getParseResult(notificationRequest);
			String decryptData = notification.getDecryptData();
			JSONObject result = JSONObject.parseObject(decryptData);
			String tradeNo = result.getString("out_trade_no");
			String refundNo = result.getString("out_refund_no");
			handleBusiness(tradeNo, refundNo);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "SUCCESS";
	}

	/**
	 * 	退款业务处理
	 * @param tradeNo		第三方订单号
	 * @param refundNo		退款订单号
	 */
	private void handleBusiness(String tradeNo,String refundNo) {
		PayOrder order = payOrderMapper.selectOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTradeNo, tradeNo));
		if(null == order) {
			return;
		}
		if(4 == order.getPayStatus()) {
			return;
		}
		order.setPayStatus(4);
		order.setExtend("退款订单号:"+refundNo+",退款时间:"+DateUtil.now());
		payOrderMapper.updateById(order);
	}

	@Override
	public AjaxResult<Object> orderRefund(PayVipValidate requestObj) {
		PayOrder order = payOrderMapper.selectOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getKuaidiNum, requestObj.getKuaidiNum())
				.eq(PayOrder::getOrderType, 1).eq(PayOrder::getPayStatus, 1));
		if(null == order) {
			return AjaxResult.failed("订单不存在");
		}
		switch (order.getPayType()) {
		case 1://余额
			User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, order.getUserId()).select(User::getId,User::getEarnings));
			if(null == user) {
				return AjaxResult.failed("用户不存在");
			}
			BigDecimal add = user.getMoney().add(order.getOrderAmount());
			user.setEarnings(add);
			userMapper.updateById(user);
			// 记录日志
			userBalanceChangeRecord(order.getUserId(), order.getId(), order.getOrderSn(), order.getOrderAmount(), add, 1, "寄快递下单-余额退回");
			break;
		case 2://微信
			//wxpayHandle.wxPayOriginalRefund(order.getTradeNo(), order.getOrderAmount(), ToolUtils.get(), WxPayConfigUtils.REFUNDNOTIFYURL);
			RefundRequestV3 requestV3 = new RefundRequestV3();
            requestV3.setTransactionId(order.getTradeNo());
            requestV3.setOutTradeNo(order.getOrderSn());
            requestV3.setOutRefundNo(ToolUtils.get());
            requestV3.setTotalAmount(AmountUtil.yuan2Fen(order.getOrderAmount().toString()));
            requestV3.setRefundAmount(AmountUtil.yuan2Fen(order.getOrderAmount().toString()));
            try {
				WxPayRefundV3Result refund = WxPayDriver.refund(requestV3);
				System.out.println("微信退款返回参数："+JSONObject.toJSONString(refund));
				order.setPayStatus(4);
				order.setExtend("退款订单号:"+requestV3.getOutRefundNo()+",退款时间:"+DateUtil.now());
				payOrderMapper.updateById(order);
				// app
				AppOrder appOrder = appOrderMapper.selectOne(new LambdaQueryWrapper<AppOrder>().eq(AppOrder::getOrdernum, requestObj.getKuaidiNum()));
				appOrder.setPaystatus(4);
				appOrder.setCancelmsg("退款订单号:"+requestV3.getOutRefundNo()+",退款时间:"+DateUtil.now());
				appOrderMapper.updateById(appOrder);
			} catch (WxPayException e) {
				e.printStackTrace();
			}
			break;
		case 3://支付宝
			String retStr = alipayHandle.aliPayOriginalRefund(order.getTradeNo(), order.getOrderAmount(), "快递订单退款");
			if(!"SUCCESS".equals(retStr)) {
				order.setExtend("退款失败,退款时间:"+DateUtil.now()+",理由："+retStr);
				payOrderMapper.updateById(order);
			}else {
				order.setPayStatus(4);
				order.setExtend("退款成功,退款时间:"+DateUtil.now());
				payOrderMapper.updateById(order);
				// app
				AppOrder appOrder = appOrderMapper.selectOne(new LambdaQueryWrapper<AppOrder>().eq(AppOrder::getOrdernum, requestObj.getKuaidiNum()));
				appOrder.setPaystatus(4);
				appOrder.setCancelmsg("退款时间:"+DateUtil.now());
				appOrderMapper.updateById(appOrder);
			}
			break;
		default:
			break;
		}
		return AjaxResult.success();
	}

	/**
	 * 	余额变动记录
	 * @param userId
	 * @param sourceId
	 * @param sourceSn
	 * @param change_amount
	 * @param left_amount
	 * @param action
	 * @param remark
	 */
	private void userBalanceChangeRecord(Integer userId,Integer sourceId,String sourceSn,BigDecimal changeAmount,BigDecimal leftAmount,Integer action,String remark) {
		LogMoney logMoney = new LogMoney();
		logMoney.setSn(ToolUtils.get());
		logMoney.setUserId(userId);
		logMoney.setSourceId(sourceId);
		logMoney.setSourceSn(sourceSn);
		logMoney.setChangeType(LogMoneyEnum.UM_DEC_PAY_KUAIDI.getCode());
		if(1 == action) {
			logMoney.setChangeType(LogMoneyEnum.BNW_INC_KUAIDI_CANCEL.getCode());	
		}
		logMoney.setChangeAmount(changeAmount);
		logMoney.setLeftAmount(leftAmount);
		logMoney.setAction(action);
		logMoney.setRemark(remark);
		logMoney.setCreateTime(TimeUtils.timestamp());
		logMoneyMapper.insert(logMoney);
	}

	@Override
	public AjaxResult<Object> noticeMessage() {
		return AjaxResult.success(expressMessageMapper.selectList(new LambdaQueryWrapper<ExpressMessage>()));
	}

	@Override
	public void handlePaidNotify(String attach, String outTradeNo, String transactionId) throws WxPayException {
		PayOrder payOrder = payOrderMapper.selectOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderSn, outTradeNo));
		if(null == payOrder) {
			throw new OperateException("订单号不存在,支付失败 :" + outTradeNo);
		}
		if(1 == payOrder.getPayStatus()) {
			throw new OperateException("订单已支付,忽略重复调用 :" + outTradeNo);
		}
		payOrder.setTradeNo(transactionId);
		payOrder.setUpdateTime(TimeUtils.timestamp());
		payOrder.setPayStatus(1);
		payOrderMapper.updateById(payOrder);
		// 修改快递订单状态
		AppOrder appOrder = appOrderMapper.selectOne(new LambdaQueryWrapper<AppOrder>().eq(AppOrder::getOrdernum, payOrder.getKuaidiNum()));
		if(null != appOrder) {
			appOrder.setPaytype(String.valueOf(payOrder.getPayType()));
			appOrder.setPayordernum(outTradeNo);
			appOrder.setPaystatus(1);
			appOrder.setPaytime(new Date());
			appOrderMapper.updateById(appOrder);
			// 通知
			String url = "https://kdapi.kdkdkd.cn:55800/kdapi/kdOrder/recOrderStatus";
			Map<String, String> param = new HashMap<String, String>();
			param.put("orderNum", payOrder.getKuaidiNum());
			param.put("payStatus", "1");
			HttpUtils.doPostJson(url, JSONObject.toJSONString(param));
		}
		
	}

	@Override
	public void kdCashbackGoldCoin(CashbackGoldCoinDto dto) {
		System.out.println("返现金币参数："+JSONObject.toJSONString(dto));
		FastType fastType = fastTypeMapper.selectOne(new LambdaQueryWrapper<FastType>().eq(FastType::getCode, dto.getCode()).last("limit 1"));
		
		if(null == fastType) {
			throw new OperateException("快递公司不存在");
		}
		if(null != fastType.getGoldCoin() && fastType.getGoldCoin().compareTo(BigDecimal.ZERO) > 0) {
			System.out.println("处理");
			userMapper.update(null, new UpdateWrapper<User>()
					.eq("id", dto.getUserId())
					.setSql("integral = integral+"+fastType.getGoldCoin()));
			logIntegralMapper.add(
					dto.getUserId(), LogMoneyEnum.UI_INC_GOODS.getCode(), fastType.getGoldCoin(), 0, "", "快递下单获得金币", "");

			eMServiceUtil.sendNoticeOfReceipt(userMapper.getEmUserName(dto.getUserId()), "本次获得金币"+fastType.getGoldCoin());
		}
		
		
	}
}
